//
// Copyright (c) 2009 All Right Reserved
//
// vl
//
// 2009-01-01
// Contains ...
using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Globalization;
using System.Linq;
using System.Text;
using JetBrains.Annotations;
namespace LargoCommon.Music
{
///
/// Harmonic Motive.
///
[Serializable]
public sealed class MelodicMotive
{
#region Fields
///
/// Unique identifier.
///
private string uniqueIdentifier;
///
/// Melodic Structures.
///
[NonSerialized]
private IEnumerable melodicStructures;
#endregion
#region Constructors
///
/// Initializes a new instance of the MelodicMotive class.
///
/// Name of the motive.
/// Melodic Structures.
public MelodicMotive(string name, IEnumerable melodicStructures) //// MelodicCore core,
: this() {
if (melodicStructures == null) {
return;
}
this.Name = name;
//// BandType = (byte)mp.BandType;
//// LineIndex = mp.Number;
//// existsMelLine = (PartType == (byte)MelodicFunction.MelodicMotion);
var barNumber = 1;
foreach (var mstruct in melodicStructures) {
if (mstruct == null) {
continue;
}
mstruct.BarNumber = barNumber++;
this.AddStructure(mstruct);
}
}
///
/// Initializes a new instance of the class.
///
public MelodicMotive() {
this.melodicStructures = new List();
}
#endregion
#region Properties
///
/// Gets or sets the name.
///
///
/// The full name.
///
[UsedImplicitly]
public string Name { get; set; } //// CA1044 (FxCop)
///
/// Gets or sets the number.
///
///
/// Property description.
///
public int Number { get; set; }
///
/// Gets or sets the octave.
///
///
/// The octave.
///
[UsedImplicitly]
public MusicalOctave Octave { get; set; } //// CA1044 (FxCop)
///
/// Gets or sets the type of the part.
///
///
/// The type of the part.
///
[UsedImplicitly]
public MelodicFunction MelodicFunction { get; set; } //// CA1044 (FxCop)
///
/// Gets or sets the first bar number.
///
///
/// The first bar number.
///
public int FirstBarNumber { get; set; }
///
/// Gets or sets the occurrence.
///
///
/// The occurrence.
///
public int Occurrence { get; set; }
///
/// Gets or sets the melodic structures.
///
///
/// The melodic structures.
///
public IEnumerable MelodicStructures {
get {
Contract.Ensures(Contract.Result>() != null);
if (this.melodicStructures == null) {
throw new InvalidOperationException("Melodic structures are null.");
}
return this.melodicStructures;
}
set => this.melodicStructures = value ?? throw new ArgumentException(Localization.LocalizedMusic.String("Argument cannot be empty."), nameof(value));
}
///
/// Gets the length.
///
/// Property description.
public int Length => ((List)this.MelodicStructures).Count;
///
/// Gets a value indicating whether this instance is empty.
///
///
/// The is empty.
///
[UsedImplicitly]
public bool IsEmpty => this.MelodicStructures.FirstOrDefault() == null;
/// Gets list of all already defined tones.
/// Property description.
public string UniqueIdentifier {
get {
if (this.uniqueIdentifier != null) {
return this.uniqueIdentifier;
}
var ident = new StringBuilder();
var melodicMotiveStructureList = this.MelodicStructures.ToList();
ident.Append(string.Format(CultureInfo.CurrentCulture, "#{0}#", melodicMotiveStructureList.Count));
//// ElementSchema, DecimalNumber, ms.StructuralCode
foreach (var b in from mms in melodicMotiveStructureList
where mms?.GetStructuralCode != null
from b in mms.GetStructuralCode
select b) {
ident.Append(b);
}
this.uniqueIdentifier = ident.ToString();
return this.uniqueIdentifier;
}
}
///
/// Gets or sets the name.
///
///
/// Property description.
///
[UsedImplicitly]
public string Shortcut { get; set; } //// CA1044 (FxCop)
#endregion
#region Static Factory methods
///
/// Simple melodic motive.
///
/// The melodic struct.
/// Returns value.
[UsedImplicitly]
public static MelodicMotive SimpleMelodicMotive(MelodicStructure melodicStruct) {
if (melodicStruct == null) {
return null;
}
var rm = new MelodicMotive();
melodicStruct.BarNumber = 1;
rm.AddStructure(melodicStruct);
return rm;
}
#endregion
#region Public methods
///
/// Melodic structure in bar.
///
/// The bar number.
/// Returns value.
public MelodicStructure MelodicStructureInBar(int barNumber) {
if (barNumber < 1) {
throw new ArgumentOutOfRangeException(nameof(barNumber), "value must be positive");
}
var cnt = this.MelodicStructures.Count();
if (cnt == 0) {
return null;
//// throw new ArgumentException("No melodic motive structure!");
}
var idx = (barNumber - 1) % cnt;
var structure = this.MelodicStructures.ElementAt(idx);
return structure;
}
///
/// Returns a that represents this instance.
///
///
/// A that represents this instance.
///
[UsedImplicitly]
public override string ToString() {
return this.Name;
}
///
/// Adds the structure.
///
/// The structure.
public void AddStructure(MelodicStructure structure) {
((List)this.MelodicStructures).Add(structure);
}
#endregion
}
}